package com.mall.consumer;

import com.mall.common.Constant;
import com.mall.mapper.WaresMapper;
import com.mall.pojo.OrderDetail;
import com.mall.service.IOrderService;
import com.mall.service.IShoppingCartService;
import com.mall.utils.AlipayUtil;
import com.mall.utils.ListByteConverterUtil;
import com.rabbitmq.client.Channel;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;

/**
 * @Package: com.mall.controller
 * @author: cxx
 * @Create: 2023/4/21-22:55
 * @Description: RabbitMQ获取队列信息
 */
@Component
@Slf4j
public class Consumer {
    @Resource
    private RedisTemplate<String, Object> redistemplate;
    @Resource
    private WaresMapper waresMapper;
    @Resource
    private IOrderService orderService;
    @Resource
    private IShoppingCartService shoppingCartService;
    @Resource
    private DefaultRedisScript<Long> incrScript;
    @Resource
    private AlipayUtil alipayUtil;

//    //监听死信队列，每次取一个消息将库存还原
//    @RabbitListener(queues = Constant.DEADQUEUE, concurrency = "1", ackMode = "MANUAL")
//    @RabbitHandler
//    @Async
//    void orderConsumer(Message msg, Channel channel) throws IOException {
//        ValueOperations<String, Object> operations = redistemplate.opsForValue();
//        ObjectMapper mapper = new ObjectMapper();
//        mapper.registerModule(new JavaTimeModule());
//        try {
//            ArrayList<OrderDetail> list = mapper.readValue(msg.getBody(), new TypeReference<>() {
//            });
//            for (OrderDetail orderDetail : list) {
//                operations.increment(orderDetail.getWaresId() + "_num", orderDetail.getNum());
//                Integer wareNum = waresMapper.getWareNum(orderDetail.getWaresId());
//                waresMapper.updateWareNum(orderDetail.getWaresId(), wareNum + orderDetail.getNum());
//            }
//            list = null;
//            log.info("订单超过15分钟未支付,库存恢复！");
//            //消息处理成功,手动确认删除消息
//            channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
//        } catch (Exception e) {
//            //消息处理失败,将消息重新放入队列中
//            channel.basicNack(msg.getMessageProperties().getDeliveryTag(), false, true);
//            e.printStackTrace();
//        }
//
//
//    }

    //监听订单队列，开启手动ACK,每次取一个消息判断其订单是否支付成功,支付成功则更新数据库中的订单支付状态,支付失败则恢复Redis中的商品数量
    @RabbitListener(queues = Constant.ORDERQUEUE, ackMode = "MANUAL", concurrency = "1")
    @RabbitHandler
    @Async(value = "myThreadPool")//使用自定义线程池实现异步消费队列中的消息
    public void paySuccess(Message msg, Channel channel) throws Exception {
        log.info(Thread.currentThread().getName());
        log.info("检查是否支付成功!");

        //将字节数组反序列化为list集合
        List<OrderDetail> list = (List<OrderDetail>) ListByteConverterUtil.byteArrayToList(msg.getBody());
        //通过订单判断支付是否成功
        try {
            boolean b = alipayUtil.ckeckPay(list.get(0).getOrderId().toString());
            if (b) {
                //修改商品库存
                list.forEach(orderDetail -> {
                    //获取当前商品库存
                    int wareNum = waresMapper.getWareNum(orderDetail.getWaresId());
                    //修改库存
                    waresMapper.updateWareNum(orderDetail.getWaresId(), wareNum - orderDetail.getNum());
                });
                //修改购物车里面的商品数量
                shoppingCartService.updateShoppingCartWaresNum(list.get(0).getUserId(), list);
                //修改支付状态为支付成功
                orderService.payUpdateStatus(list, 2);
                log.error("支付成功,修改支付状态!");
                // 手动确认消息的处理结果
                channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);

            } else {
                ValueOperations<String, Object> operations = redistemplate.opsForValue();
                //支付失败，Redis缓存商品库存还原
                list.forEach(orderDetails -> {
                    List<String> keys = Collections.singletonList(orderDetails.getWaresId() + "_num");
                    Long execute = redistemplate.execute(incrScript, keys, orderDetails.getNum());
                    //将内存标记标记为存在商品
                    Constant.MEMORY_TAGS.put(orderDetails.getWaresId().toString(), false);
                });
                //修改支付状态为支付失败
                orderService.payUpdateStatus(list, 0);
                list = null;
                log.error("订单超过15分钟未支付,库存恢复！");
                //消息处理成功,手动确认删除消息
                channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
            }
        } catch (Exception e) {
            //出现异常,调用basicNack方法将消息重新放回队列中并设置requeue为true，表示该消息需要重新投递到队列中
            channel.basicNack(msg.getMessageProperties().getDeliveryTag(), false, true);
            e.printStackTrace();
        }

    }

}


